using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Konst3d.Efficiency;
using Konst3d.Efficiency.Suite;

namespace PEM
{
    internal partial class BuysViewModel: ViewModelBase
    {
        #region Types

        internal delegate void EventHandler(ViewModelBase sender);

        public enum BuyStateFilter
        {
            Any,
            Active,
            Postponed,
            Cancelled,
            Completed
        }

        public enum BuySorting
        {
            Title,
            State,
            Severity,
            Price,
            DeadLine,
            Created
        }

        #endregion // Types

        #region Events

        public event EventHandler SuiteOpened;
        public event EventHandler SuiteClosed;
        public event EventHandler SuiteCreated;
        public event EventHandler SuiteDeleted;
        public event EventHandler BuySelected;
        public event EventHandler SelectedBuyStateChanged;

        #endregion // Events

        #region Properties

		public bool HasItems
		{
			get
			{
				return Suite != null ? Suite.Buys.Count > 0 : false;
			}
		}

        public ObservableList2<IBuy> Buys
        {
            get;
            private set;
        }

        public IEnumerable<BuyStateFilter> StateFilters
        {
            get;
            private set;
        }

        public BuyStateFilter StateFilter
        {
            get
            {
                return _stateFilter;
            }
            set
            {
                if (_stateFilter != value)
                {
                    _stateFilter = value;
                    UpdateBuyList();
                }
            }
        }

        public IEnumerable<BuySorting> SortingOptions
        {
            get;
            private set;
        }

        public BuySorting Sorting
        {
            get
            {
                return _sorting;
            }
            set
            {
                if (_sorting != value)
                {
                    _sorting = value;
                    UpdateBuyList();
                }
            }
        }

        public SortingDirection SortingDirection
        {
            get
            {
                return _sortingDirection;
            }
            set
            {
                if (value != _sortingDirection)
                {
                    _sortingDirection = value;
                    UpdateBuyList();
                }
            }
        }

        public IBuy SelectedBuy
        {
            get
            {
                return _selectedBuy;
            }
            set
            {
                _selectedBuy = value;

                if (BuySelected != null)
                {
                    BuySelected(this);
                }

				NotifyPropertyChanged("SelectedBuy");
            }
        }

        public CommandsCollection Commands
        {
            get;
            private set;
        }

        public IEfficiencySuite Suite
        {
            get
            {
                return _parentModel.Suite;
            }
        }

        #endregion // Properties

        #region Constructor

        public BuysViewModel(Window parentWindow, MainWindowViewModel parentModel)
        {
            Contract.Requires(parentWindow != null);
            Contract.Requires(parentModel  != null);

            _parentWindow = parentWindow;
            _parentModel = parentModel;

            _parentModel.SuiteOpened += OnSuiteOpened;
            _parentModel.SuiteClosed += OnSuiteClosed;
            _parentModel.SuiteCreated += OnSuiteCreated;
            _parentModel.SuiteDeleted += OnSuiteDeleted;

            //
            // create comparers that will be used during buys sorting
            //
            _sortingComparers.Add(BuySorting.Title,    (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? String.Compare(x.Title, y.Title) : String.Compare(y.Title, x.Title);
            });
            _sortingComparers.Add(BuySorting.State,    (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? (int)x.State - (int)y.State : (int)y.State - (int)x.State;
            });
            _sortingComparers.Add(BuySorting.Severity, (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? (int)x.Severity - (int)y.Severity : (int)y.Severity - (int)x.Severity;
            });
            _sortingComparers.Add(BuySorting.Price,    (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? (int)x.Price - (int)y.Price : (int)y.Price - (int)x.Price;
            });
            _sortingComparers.Add(BuySorting.DeadLine, (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? DateTime.Compare(x.DeadLine, y.DeadLine) : DateTime.Compare(y.DeadLine, x.DeadLine);
            });
            _sortingComparers.Add(BuySorting.Created,  (IBuy x, IBuy y) => {
                return _sortingDirection == SortingDirection.Ascending ? DateTime.Compare(x.Created, y.Created) : DateTime.Compare(y.Created, x.Created);
            });

            StateFilters = new BuyStateFilter[] { BuyStateFilter.Any, BuyStateFilter.Active, BuyStateFilter.Postponed, BuyStateFilter.Completed, BuyStateFilter.Cancelled };
            SortingOptions = new BuySorting[] { BuySorting.Title, BuySorting.State, BuySorting.Severity, BuySorting.Price, BuySorting.DeadLine, BuySorting.Created };
            Buys = new ObservableList2<IBuy>();
            Commands = new CommandsCollection(this);

            _createEditBuyDlg = new CreateEditBuyDialog();
        }

        #endregion // Constructor

        #region Overriden Methods

        protected override void DisposeManaged()
        {
            base.DisposeManaged();

            _createEditBuyDlg.Close();
            _createEditBuyDlg = null;

            _parentModel.SuiteOpened -= OnSuiteOpened;
            _parentModel.SuiteClosed -= OnSuiteClosed;
            _parentModel.SuiteCreated -= OnSuiteCreated;
            _parentModel.SuiteDeleted -= OnSuiteDeleted;
            _parentModel = null;
        }

        #endregion // Overriden Methods

        #region Event Handlers

        private void OnSuiteOpened(MainWindowViewModel sender)
        {
            UpdateBuyList();

            if (SuiteOpened != null)
            {
                SuiteOpened(this);
            }
        }

        private void OnSuiteClosed(MainWindowViewModel sender)
        {
            UpdateBuyList();

            if (SuiteClosed != null)
            {
                SuiteClosed(this);
            }
        }

        private void OnSuiteCreated(MainWindowViewModel sender)
        {
            UpdateBuyList();

            if (SuiteCreated != null)
            {
                SuiteCreated(this);
            }
        }

        private void OnSuiteDeleted(MainWindowViewModel sender)
        {
            UpdateBuyList();

            if (SuiteDeleted != null)
            {
                SuiteDeleted(this);
            }
        }

        #endregion // Event Handlers

        #region Private Methods

        private void UpdateBuyList()
        {
            Buys.Clear();

            if (Suite != null)
            {
                foreach (var buy in Suite.Buys)
                {
                    if (IsBuyMutches(buy, _stateFilter))
                    {
                        Buys.Add(buy);
                    }
                }

                Buys.Sort(_sortingComparers[_sorting]);
            }

			NotifyPropertyChanged("HasItems");
        }

        private static bool IsBuyMutches(IBuy buy, BuyStateFilter filter)
        {
            Contract.Requires(buy != null);

            bool matches = false;

            switch (filter)
            {
                case BuyStateFilter.Any:
                    matches = true;
                    break;

                case BuyStateFilter.Active:
                    matches = buy.State == BuyState.Active;
                    break;

                case BuyStateFilter.Postponed:
                    matches = buy.State == BuyState.Paused;
                    break;

                case BuyStateFilter.Completed:
                    matches = buy.State == BuyState.Completed;
                    break;

                case BuyStateFilter.Cancelled:
                    matches = buy.State == BuyState.Cancelled;
                    break;
            }

            return matches;
        }

        #endregion // Private Methods

        #region Fields

        private Window _parentWindow;
        private MainWindowViewModel _parentModel;
        private BuyStateFilter _stateFilter = BuyStateFilter.Any;
        private BuySorting _sorting = BuySorting.Title;
        private SortingDirection _sortingDirection = SortingDirection.Ascending;
        private IBuy _selectedBuy;
        private CreateEditBuyDialog _createEditBuyDlg;
        private Dictionary<BuySorting, Comparison<IBuy>> _sortingComparers = new Dictionary<BuySorting, Comparison<IBuy>>();

        #endregion // Fields
    }
}
